#region (c) 2014 THN Solutions LLC. - All rights reserved
/*
THN TELEPORT version 2

Copyright (c) 2014, THN Solutions LLC. ( www.ThnSolutions.com )
Author: Nguyễn, M. Hải                 ( www.Minh-Hai.com     )
All rights reserved.

This library is dual-licensed.
  + For commercial software, please obtain a commercial license from THN Solutions LLC.

  + For free software, this library is licensed under GPL version 3. A summary of GPLv3 is
    listed below. You should also find a copy of GPLv3 as file License_GPLv3.txt included
	with the source-code files.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 3 as published by
    the Free Software Foundation  of the License.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#endregion

#region Record of Change
//             							CHANGE HISTORY
// -------------------------------------------------------------------------------------
// |   DATE    | DEVELOPER  | DESCRIPTION                                              |
// -------------------------------------------------------------------------------------
// | 28-Dec-09 | HaiNM      | First creation.                                          |
// -------------------------------------------------------------------------------------
//
#endregion

#region Record of Audit
//             							REVIEW HISTORY
// -------------------------------------------------------------------------------------
// |   DATE    | REVIEWER   | NOTES                                                    |
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
//
#endregion

#region Using directives
using System;
using System.IO;
using System.Web;

using Thn;
using Thn.IO;
using Thn.Communication;
using Thn.Communication.Teleporting;
using Thn.Communication.Teleporting.Settings;
using Thn.Application.Configuration;
#endregion

namespace Thn.Communication.Teleporting.Connectors.WebRequest
{
    /// <summary>
    /// A server-side connector for Teleport using <see cref="IHttpHandler"/>.
    /// </summary>
#if DEBUG
    public
#else
    public
#endif
 class ServerConnector : ITeleportConnector, IHttpHandler
    {
        #region Fields
        StreamContextReader mReader = null;
        StreamContextWriter mWriter = null;
        bool mIsInitialized = false;
        #endregion

        #region On Initialize
        /// <summary>
        /// Setup this connector.
        /// </summary>
        protected virtual void OnInitialize() { }
        #endregion

        #region Properties
        #endregion

        #region Apply Configuration
        /// <summary>
        /// Read parameters from configuration.
        /// </summary>
        void ApplyConfiguration(ConfigSection section)
        {
            ////Port
            //string tmp = section["Port"];
            //if ((tmp != null) && (tmp != string.Empty))
            //{
            //    #region Save Port
            //    Exception error = null;
            //    try
            //    {
            //        mPort = int.Parse(tmp);
            //    }
            //    catch (Exception ex)
            //    {
            //        error = ex;
            //    }
            //    #endregion
            //}
            ////Uri
            //tmp = section["Uri"];
            //if ((tmp != null) && (tmp != string.Empty)) mUri = tmp;

            ////Channel
            //tmp = section["ChannelType"];
            //if ((tmp != null) && (tmp != string.Empty))
            //{
            //    string ct = tmp.Trim().ToUpper();
            //    if (ct == "TCP") mChannelType = ChannelType.Tcp;
            //    else if (ct == "HTTP") mChannelType = ChannelType.Http;
            //}

            ////Formatter
            //tmp = section["Formatter"];
            //if ((tmp != null) && (tmp != string.Empty))
            //{
            //    string fm = tmp.Trim().ToUpper();
            //    if (fm == "BINARY") mFormatter = FormatterType.Binary;
            //    else if (fm == "SOAP") mFormatter = FormatterType.Soap;
            //}

            ////AutoStart
            //tmp = section["AutoStart"];
            //if ((tmp != null) && (tmp != string.Empty))
            //{
            //    tmp = tmp.ToUpper();
            //    if (tmp == "TRUE") mAutoStart = true;
            //    else if (tmp == "FALSE") mAutoStart = false;
            //}
        }
        #endregion

        #region ITeleportConnector Members

        #region Teleporter
        private ITeleporter mTeleporter;
        /// <summary>
        /// Gets/Sets the teleporter this connector shall be connecting for.
        /// <para>When unassigned, the connector shall use the default teleporter.</para>
        /// </summary>
        public ITeleporter Teleporter
        {
            get
            {
                ITeleporter result = null;
                if (mTeleporter != null) result = mTeleporter;
                else result = Teleport.Teleporter;

                return result;
            }
            set { mTeleporter = value; }
        }
        #endregion

        #region Configuration
        private ConfigSection mConfiguration;
        /// <summary>
        /// Gets/Sets a custom configuration for initialization.
        /// </summary>
        public ConfigSection Configuration
        {
            get { return mConfiguration; }
            set
            {
                mConfiguration = value;
                if (mConfiguration != null) ApplyConfiguration(mConfiguration);
                else Thn.Exceptions.NullArgumentException.Publish("Configuration");
            }
        }
        #endregion

        #region Initialize
        /// <summary>
        /// Prepare this connector.
        /// </summary>
        public void Initialize()
        {
            OnInitialize();
            mIsInitialized = true;
            //Start server automatically
            //if (mAutoStart) Start();

            //Config for remote logging
            //Thn.Log.ThreadedOperation = true;
            //Thn.Communication.Teleporting.Logging.RemotingLogger logger = new Thn.Communication.Teleporting.Logging.RemotingLogger();
            //logger.Subscribe();
        }
        #endregion

        #endregion

        #region IHttpHandler Members

        #region Is Reusable
        /// <summary>
        /// Gets a value indicating whether another request can use the <see cref="IHttpHandler"/>.
        /// </summary>
        public bool IsReusable
        {
            get { return true; }
        }
        #endregion

        #region Process Request
        /// <summary>
        /// Process HTTP web request.
        /// </summary>
        void IHttpHandler.ProcessRequest(HttpContext context)
        {
            //Log.Debug("SERVER - Process Request");
            string result = "";
            
            #region Initialize

            if (!mIsInitialized) Initialize();
            #region Defensive tracing
            else
            {
                //already initialized, no need to do it again
            }
            #endregion

            #endregion

            #region Read request
            Stream content = context.Request.InputStream;
            if (mReader != null) mReader.Source = content;
            else mReader = new StreamContextReader(content);

            //read contents
            string gateway = mReader.ReadString();
            string method = mReader.ReadString();
            string encodedArgs = mReader.ReadString();

            //close stream
            content.Close();

            if (TeleportSettings.Tracing)
            {
                Log.Debug("Received request - Gateway: {0} Method: {1} EncodedArgs: {2}", gateway, method, encodedArgs);
            }
            #endregion

            #region Execute request
            result = Teleporter.ProcessRequest(gateway, method, encodedArgs);
            #endregion

            #region Reply response
            content = context.Response.OutputStream;
            if (mWriter != null) mWriter.Target = content;
            else mWriter = new StreamContextWriter(content);

            //write response            
            mWriter.Write(result);
            content.Close();
            #endregion

            //context.Response.Status = "OK";
        }
        #endregion

        #endregion

        #region Constructors
        /// <summary>
        /// Default constructor.
        /// </summary>
        public ServerConnector()
        { }
        #endregion
    }
}
